const {
	Controller
} = require('uni-cloud-router');
const crypto = require('crypto');
module.exports = class PaymentController extends Controller {
	constructor(ctx) {
		super(ctx)
	}
	/**
	 * 获得支付订单信息
	 * @param {Object} data
	 * @param {Object} module
	 * @param {Object} context
	 */
	async info() {
		//再次查询支付订单金额，支付方式
		let {
			id,
			module
		} = this.ctx.data;
		let userInfo = await this.service.user.user.getCurrentUserInfo(["balance"])
		// let order = await this.service.order[module].info(id, userInfo, this.ctx.data);
		let order = await this.getOrderInfoWithCache(id, module, userInfo);
		let payment = this.ctx.getConfigs.platformConfigs("payment");
		let paymentList = [];
		userInfo.balance = !userInfo.balance ? 0 : userInfo.balance;

		for (let key in payment) {
			//前后台支付区分
			if (!payment[key].admin) {
				let config = await this.service.payment[key].prepay(userInfo);
				paymentList.push({
					//支付方式排序index，asc
					index: payment[key].index ? payment[key].index : 0,
					...config,
					name: payment[key].payName
				});
			}
		}
		//支付方式排序
		paymentList.sort(function(a, b) {
			return a.index - b.index;
		})

		return {
			order: {
				id,
				...order,
				shop: {},
				payments: {},
				module
			},
			balance: userInfo.balance,
			paymentList
		}
	}

	/**
	 * 支付参数，余额支付直接扣费，并回调支付完成方法
	 * @param {Object} data
	 * @param {Object} module
	 * @param {Object} context
	 */
	async pay() {
		let {
			type, //支付方式
			id, //订单id
			module //订单类型
		} = this.ctx.data;
		// let canCombinePay = ["wxpay_v3", "wxpay_partner_v3"].indexOf(type) != -1;
		const {
			uid
		} = this.ctx.auth;
		console.log("开始支付")
		//获取当前用户信息
		let userInfo = await this.service.user.user.getCurrentUserInfo(["balance", "wx_openid", "ali_openid"]);
		console.log("获取当前用户信息完成")

		//可能存在多个订单合并支付
		let order = await this.getOrderInfoWithCache(id, module, userInfo, async (res, index) => {
			console.log("获取订单完成")
			let outTradeNo = [
					Date.now(),
					crypto.createHash("md5").update(uid).digest("hex").substring(0, 16), index
				]
				.join("");
			res.outTradeNo = outTradeNo
			//生成支付单号，避免造成重复支付
			await this.service.order[module].updateOutTradeNo(res);
			console.log("更新订单支付编号完成")
		});
		if (!order) {
			return {
				code: -1,
				message: "订单不存在或已支付"
			};
		}
		//http://www.xxx.com/http/mall/payment/notify/__UNI__9E9D6A0/app-plus/wxpay/mall
		order.notifyUrl = this.ctx.getConfigs.paymentNotifyUrl(type, module);
		console.log("order.notifyUrl", order.notifyUrl)
		if (order.combineOrder) {
			//合并支付订单号
			order.outTradeNo = [
					Date.now(),
					crypto.createHash("md5").update(uid).digest("hex").substring(0, 17)
				]
				.join("");
			order.notifyUrl += "/combine";
			//订单写入缓存
			await this.ctx.dbcache("order_out_trade_no_" + order.outTradeNo, null, 3600 * 24, async () => {
				return order;
			});
			//获取支付参数
			return await this.service.payment[type].combineTransactions(order, userInfo, async (payInfo) => {
				console.log("回调处理订单状态")
				//处理各类订单支付完成之后的回调
				for (let i = 0; i < order.children.length; i++) {
					let order2 = order.children[i];
					// for await (const order2 of order.children) {
					//分别显示不同的金额
					payInfo.totalFee = order2.total_fee;
					await this.service.order[module].afterPayment(payInfo, order2);
				}
				return "ok";
			});
		} else {
			//获取支付参数
			return await this.service.payment[type].app(order, userInfo, async (payInfo) => {
				console.log("回调处理订单状态")
				return this.service.order[module].afterPayment(payInfo, order);
			});
		}

	}

	async getOrderInfoWithCache(id, module, userInfo, callback) {
		if (typeof(id) == "string" && id.indexOf(",") > -1) {
			let ids = id.split(",");
			//这个模式下，订单号没有用处
			let order = await this.ctx.dbcache("order_" + ids.join("_"), null, 3600, async () => {
				let data = {
					module,
					ids,
					total_fee: 0,
					user_id: "",
					title: "",
					body: "",
					combineOrder: true, //合并订单
					children: []
				}
				//nodejs 12支持的写法
				for (let i = 0; i < ids.length; i++) {
					let id2 = ids[i];
					// for await (const id2 of ids) {
					let order2 = await this.service.order[module].info(id2, userInfo, this.ctx
						.data);
					data.total_fee += order2.total_fee;
					data.children.push(order2);
					data.user_id = order2.user_id;
					data.title = order2.title;
					data.body += order2.body;
				}
				return data;
			});
			//更新订单号
			let index = 0;
			for (let i = 0; i < order.children.length; i++) {
				let order2 = order.children[i];
				// for await (const order2 of order.children) {
				if (callback) {
					await callback(order2, index)
					index++;
				}
			}
			return order;
		}
		//单条订单不缓存，防止从后台修改订单金额
		let order = await this.service.order[module].info(id, userInfo, this.ctx
			.data);
		if (callback) {
			await callback(order, 0)
		}
		return order;
	}
	/**
	 * 取消订单，全额退款
	 */
	async cancel() {
		let {
			type, //支付方式
			id, //订单id
			module //订单类型
		} = this.ctx.data;

		const {
			uid
		} = this.ctx.auth;
		return await this.service.order[module].cancel(id, uid, async (order) => {
			if (order && order.payInfo) {
				//已付款订单，取消订单
				await this.service.payment[order.payInfo.type].refund({
					payInfo: order.payInfo,
					platform: order.platform,
					uid: order.user_id,
					outTradeNo: order.payInfo.outTradeNo,
					outRefundNo: order._id,
					totalFee: order.total_fee, //支付总金额
					refundFee: order.total_fee, //退款金额
					refundDesc: "取消订单", //退款原因
				})
			}
		});
	}

	/**
	 *  支付回调、payment/notify
	 *  https://uniapp.dcloud.io/uniCloud/unipay?id=%e6%94%af%e4%bb%98%e7%bb%93%e6%9e%9c%e9%80%9a%e7%9f%a5%e5%a4%84%e7%90%86
	 */
	async notify() {
		let {
			subModule
		} = this.ctx.query;
		// subModule = ['mp-weixin', 'wxpay_partner_v3', 'mall']
		//平台app-plus
		let platform = subModule[0];
		//支付类型，wxpay，alipay
		let provider = subModule[1];
		//新增第三个参数，支付模块
		let model = subModule[2];
		//组合支付
		let combine = false;
		if (subModule.length > 3) {
			combine = subModule[3];
		}
		let config = this.ctx.getConfigs.config(`${platform}.payment.${provider}`);
		console.log("payment config", `${platform}.payment.${provider}`);
		if (!config) {
			//其他支付
			return "支付方式错误";
		}
		//传递用户使用平台信息，方便后续操作
		config.platform = platform
		let {
			header,
			result
		} = await this.service.payment[provider].verify(config, this.ctx.event, async (payInfo) => {
			if (combine) {
				//从缓存读取临时合并订单
				let order = await this.ctx.dbcache("order_out_trade_no_" + payInfo.outTradeNo);
				if (order) {
					for (let i = 0; i < order.children.length; i++) {
						let order2 = order.children[i];
						// for await (const order2 of order.children) {
						//分别显示不同的金额
						payInfo.totalFee = order2.total_fee;
						await this.service.order[module].afterPayment(payInfo, order2);
					}
				}
			} else {
				//处理各类订单支付完成之后的回调
				return this.service.order[model].afterPayment(payInfo);
			}
		})
		//返回字符串类型
		if (header) {
			this.ctx.headers["content-type"] = header;
		}
		// this.ctx.headers["content-type"] = "text/xml;charset=utf-8";
		return result;
	}
}
